﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Globalization;
using System.CodeDom.Compiler;

namespace SmsReader
{
    class Program
    {
        static string fileName = "SMS.DTC";
        static byte[] buffer;

        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                if (args[0] == "-h")
                {
                    Usage();
                    Environment.Exit(1);
                }
                fileName = args[0];
            }
            Console.WriteLine("Leggo il file : {0}", fileName);
            if (File.Exists(fileName))
            {
                FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                long fl = fStream.Length;
                Console.WriteLine("Lunghezza file {0} bytes", fl);
                // Create a buffer to hold the stream bytes
                buffer = new byte[fl];
                // Read the bytes from this stream
                fStream.Read(buffer, 0, (int)fl);
                // Now we can close the stream
                fStream.Flush();
                fStream.Close();

                // write some data
                bool previousIsZero = false;
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < fl; i++)
                {
                    if (buffer[i] != 0)
                    {
                        sb.AppendFormat("{0}>{1} - {2}\n", i, buffer[i], char.ConvertFromUtf32(buffer[i]));
                    }
                }

                byte[] header = new byte[336];
                for (int j = 0; j < 336; j++)
                {
                    header[j] = buffer[j];
                }

                List<Message> listMess = new List<Message>();
                for (int j = 9170; j < fl; j+=8823)
                {
                    int k = j;
                    Message mess = new Message();
                    mess.index = Byte2Int(k, 4);
                    k += 7;
                    mess.direction = Byte2String(k, 1);
                    k += 2;
                    mess.number = Byte2String(k, 501);
                    k += 502;
                    mess.content = Byte2String(k, 8199);
                    k += 8200;
                    mess.time = Byte2DateTime(k, 13);
                    k += 62;
                    mess.longsmsid = Byte2String(k, 9);
                    k += 30;
                    mess.position = Byte2String(k, 1);
                    listMess.Add(mess);
                }

                // print with indent
                System.IO.StringWriter baseTextWriter = new System.IO.StringWriter();
                System.CodeDom.Compiler.IndentedTextWriter indentWriter = new IndentedTextWriter(baseTextWriter, "    ");
                // Sets the indentation level.
                indentWriter.Indent = 0;
                string[] lines;
                listMess.Sort(Comparison);
                foreach (Message m in listMess)
                {
                    if (m.longsmsid == "0")
                    {
                        lines = m.Print().Split("\n".ToCharArray());
                        if (m.position == "0")
                        {
                            indentWriter.Indent++;
                            foreach (string line in lines)
                            {
                                indentWriter.WriteLine(line.Trim("\r\n".ToCharArray()));
                            }
                            indentWriter.Indent--;
                        }
                        else
                        {
                            foreach (string line in lines)
                            {
                                indentWriter.WriteLine(line.Trim("\r\n".ToCharArray()));
                            }
                        }
                        indentWriter.WriteLine();
                    }
                }
                // Return the resulting string from the base StringWriter.
                File.WriteAllText("data2.txt", baseTextWriter.ToString() );

                //File.WriteAllText("data.txt", sb.ToString());
                Environment.Exit(1);

                //File.WriteAllText("data.txt", sb.ToString());
                StringBuilder sbmess = new StringBuilder();
                listMess.Sort(Comparison);
                foreach (Message m in listMess)
                {
                    sbmess.AppendLine(((m.position == "0")?"    ":"") + m.Print());
                }
                File.WriteAllText("data2.txt", sbmess.ToString());
            }
            else
            {
                Console.WriteLine("File not found");
            }
            Console.Write("Hit any key...");
            Console.ReadKey();
        }

        private static void Usage()
        {
            Console.WriteLine("Legge gli sms contenuti in Mobile Partner e crea un file di nome data2.txt con i messaggi estratti, ordinati per data e formattati.");
            Console.WriteLine("SmsReader [-h] [filename]");
            Console.WriteLine("-h mostra questo messaggio");
            Console.WriteLine("filename è il path del file sms.dtc contenente i messaggi");
        }

        private static int Comparison(Message x, Message y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    return x.time.CompareTo(y.time);
                }
            }
        }

        private static DateTime Byte2DateTime(int k, int p)
        {
            // 2009 812 9 539
            // convertirlo in 20090812090539
            // yyyyMMddHHmmss

            StringBuilder sb = new StringBuilder();
            for (int j = k; j <= k + p; j++)
            {
                sb.Append(char.ConvertFromUtf32(buffer[j]).Replace(" ", "0"));
            }
            //Console.WriteLine(sb.ToString());
            return DateTime.ParseExact(sb.ToString(), "yyyyMMddHHmmss", CultureInfo.CurrentCulture);
        }

        private static int Byte2Int(int k, int p)
        {
            StringBuilder sb = new StringBuilder();
            for (int j = k; j < k+p; j++)
            {
                //Console.WriteLine("{0}>{1} - {2}\n", j, buffer[j], char.ConvertFromUtf32(buffer[j]));
                if (buffer[j] != 0)
                {
                    sb.Append(buffer[j].ToString());
                }
            }
            return int.Parse(sb.ToString());
        }

        private static string Byte2String(int k, int p)
        {
            StringBuilder sb = new StringBuilder();
            for (int j = k; j < k+p; j++)
            {
                if (buffer[j] != 0)
                {
                    if (buffer[j] == 195)
                    {
                        sb.Append(System.Text.Encoding.UTF8.GetString(buffer, j, 2));
                        j++;
                    }
                    else
                    {
                        sb.Append(char.ConvertFromUtf32(buffer[j]));
                    }
                }
            }
            return sb.ToString();
        }

        public static TestStruct FromBinaryReaderField()
        {
            FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);

            TestStruct s = new TestStruct();//New struct
            s.longField = br.ReadInt64();//Fill the first field
            s.byteField = br.ReadByte();//Fill the second field
            s.byteArrayField = br.ReadBytes(16);//...
            s.floatField = br.ReadSingle();//...
            return s;
        }

        private string CreateMultilevelIndentString()
        {
            // Creates a TextWriter to use as the base output writer.
            System.IO.StringWriter baseTextWriter = new System.IO.StringWriter();

            // Create an IndentedTextWriter and set the tab string to use 
            // as the indentation string for each indentation level.
            System.CodeDom.Compiler.IndentedTextWriter indentWriter = new IndentedTextWriter(baseTextWriter, "    ");

            // Sets the indentation level.
            indentWriter.Indent = 0;

            // Output test strings at stepped indentations through a recursive loop method.
            WriteLevel(indentWriter, 0, 5);

            // Return the resulting string from the base StringWriter.
            return baseTextWriter.ToString();
        }

        private void WriteLevel(IndentedTextWriter indentWriter, int level, int totalLevels)
        {
            // Output a test string with a new-line character at the end.
            indentWriter.WriteLine("This is a test phrase. Current indentation level: " + level.ToString());

            // If not yet at the highest recursion level, call this output method for the next level of indentation.
            if (level < totalLevels)
            {
                // Increase the indentation count for the next level of indented output.
                indentWriter.Indent++;

                // Call the WriteLevel method to write test output for the next level of indentation.
                WriteLevel(indentWriter, level + 1, totalLevels);

                // Restores the indentation count for this level after the recursive branch method has returned.
                indentWriter.Indent--;
            }
            else
                // Outputs a string using the WriteLineNoTabs method.
                indentWriter.WriteLineNoTabs("This is a test phrase written with the IndentTextWriter.WriteLineNoTabs method.");

            // Outputs a test string with a new-line character at the end.
            indentWriter.WriteLine("This is a test phrase. Current indentation level: " + level.ToString());
        }
    }

    class TestStruct
    {
        public long longField;
        public byte byteField;
        public byte[] byteArrayField;
        public float floatField;
    }
}
